<template>
  <div v-loading="loading" class="data-table" element-loading-text="查询数据中">
    <div v-if="showField" class="search-container">
      <el-form
        ref="ruleForm"
        :class="{
          'four-column': col === 4 && !inline,
          'three-column': col === 3 && !inline,
          'two-column': col === 2 && !inline
        }"
        :inline="inline"
        :label-width="labelWidth"
        :model="queryFields"
        :rules="rules"
      >
        <template>
          <el-form-item
            v-for="field in fields"
            :key="field.prop"
            :label="field.label"
            :prop="field.prop"
          >
            <el-input
              v-if="field.type === 'input'"
              v-model.trim="queryFields[field.prop]"
              clearable
              placeholder="请输入"
            />
            <el-select
              v-else-if="field.type === 'select'"
              v-model="queryFields[field.prop]"
              clearable
              :filterable="field.filterable"
              :multiple="field.multiple"
              collapse-tags
              placeholder="请选择"
            >
              <template v-if="field.optionGroup">
                <el-option-group
                  v-for="group in field.options"
                  :key="group.label"
                  :label="group.label"
                >
                  <el-option
                    v-for="item in group.options"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-option-group>
              </template>
              <template v-else>
                <el-option
                  v-for="pos in field.options"
                  :key="pos.value"
                  :label="pos.label"
                  :value="pos.value"
                />
              </template>
            </el-select>
            <el-cascader
              v-else-if="field.type === 'cascader'"
              v-model="queryFields[field.prop]"
              :options="field.options"
              :props="field.defaultParams || defaultParams"
              expand-trigger="hover"
              clearable
              placeholder="请选择"
            />
            <el-date-picker
              v-else-if="field.type === 'date'"
              v-model="queryFields[field.prop]"
              format="yyyy-MM-dd"
              placeholder="选择日期"
              type="date"
              clearable
              value-format="yyyyMMdd"
            />
            <el-date-picker
              v-else-if="field.type === 'month'"
              v-model="queryFields[field.prop]"
              format="yyyy-MM"
              placeholder="选择日期"
              type="month"
              clearable
              value-format="yyyyMM"
            />
            <el-date-picker
              v-else-if="field.type === 'dates'"
              v-model="queryFields[field.prop]"
              :value-format="field.valueFormat || 'yyyyMMdd'"
              end-placeholder="结束日期"
              format="yyyy-MM-dd"
              start-placeholder="开始日期"
              type="daterange"
              clearable
            />
            <el-radio-group
              v-else-if="field.type === 'radio'"
              v-model="queryFields[field.prop]"
              clearable
            >
              <el-radio v-for="opts in field.options" :key="opts.label" :label="opts.value">
                {{ opts.label }}
              </el-radio>
            </el-radio-group>
            <tree-select
              v-else-if="field.type === 'tree-select'"
              ref="treeS"
              v-model="queryFields[field.prop]"
              :query-all="field.queryAll || false"
              :select-type="field.selectType"
              :select-url="field.selectUrl"
              :value-indust="queryFields[field.prop]"
            />
          </el-form-item>

          <div v-if="btnInline" class="btn-after-fields">
            <el-button type="primary" @click="search">查询</el-button>
            <el-button v-if="needAuth ? addBtn : addBtnExist" @click="addData">新增</el-button>
            <slot name="extrabtn" />
          </div>
        </template>
      </el-form>

      <el-row v-if="!btnInline" class="textC marb20">
        <el-button type="primary" @click="search">查询</el-button>
        <el-button v-if="needAuth ? addBtn : addBtnExist" @click="addData">新增</el-button>
        <slot name="extrabtn" />
      </el-row>
    </div>
    <div class="form-container">
      <div class="form-header">
        <div class="table">
          <slot name="tableHeaderTip" />
          <div v-if="$slots.tableExtrabtn" class="textR">
            <slot name="tableExtrabtn" />
          </div>
          <table-mixin
            ref="tableMixin"
            :checkbox="checkbox"
            :row-single="rowSingle"
            :opera-btns="operaBtns"
            :page-no="pageNo"
            :page-size="pageSize"
            :page-sizes="pageSizes"
            :selectable="selectable"
            :set-show-btn="setShowBtn"
            :table-data="tableData"
            :table-columns="tableColumns"
            :total-size="totalSize"
            @handleData="handleData"
            @handleSelectionChange="handleSelectionChange"
            @pageChange="pageChange"
            @rowSingleChange="rowSingleChange"
            @sizeChange="sizeChange"
            @tableDataChanged="tableDataChanged"
          >
            <template v-slot:table-pre-column>
              <slot name="table-pre-column" />
            </template>
            <template v-slot:table-column>
              <slot name="table-column" />
            </template>
          </table-mixin>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import forEach from 'lodash/forEach'
import { getTableBtns, operaBtns } from '@/utils/operaBtn'
import { getCurrentMonthDay } from '@/utils/index'
import request from '@/utils/request'

import Vue from 'vue'

export default {
  name: 'FormTable',
  props: {
    queryurl: {
      type: String,
      default() {
        return ''
      }
    },
    ifMock: {
      type: Boolean,
      default: false
    },
    fields: {
      type: Array,
      default() {
        return []
      }
    },
    showField: {
      type: Boolean,
      default() {
        return true
      }
    },
    extraFields: {
      type: Array,
      default() {
        return []
      }
    },
    col: {
      type: Number,
      default() {
        return 4
      }
    },
    inline: {
      type: Boolean,
      default: false
    },
    btnInline: {
      type: Boolean,
      default: false
    },
    autoQuery: {
      type: Boolean,
      default() {
        return true
      }
    },
    tableColumns: {
      type: Array,
      default() {
        return []
      }
    },
    checkbox: {
      type: Boolean,
      default() {
        return false
      }
    },
    rowSingle: {
      type: Boolean,
      default() {
        return false
      }
    },
    handlebtns: {
      type: Array,
      default() {
        return []
      }
    },
    needAuth: {
      type: Boolean,
      default() {
        return false
      }
    },
    beforeQueryPage: {
      type: Function,
      default() {
        return null
      }
    },
    setShowBtn: {
      type: Function,
      default() {
        return true
      }
    },
    selectable: {
      type: Function,
      default() {
        return true
      }
    }
  },
  data() {
    return {
      loading: false,
      queryFields: {},
      rules: {},
      tableResults: {},
      pageSize: 10,
      totalSize: 0,
      pageNo: 1,
      pageSizes: [10, 20, 50, 100],
      tableData: [],
      addBtn: false,
      operaBtns: []
    }
  },
  computed: {
    addBtnExist() {
      return this.handlebtns.indexOf('add') > -1
    },
    labelWidth() {
      if (this.inline) {
        return null
      }
      let labelNum = 0
      this.fields.forEach((field) => {
        labelNum = field.label.length > labelNum ? field.label.length : labelNum
      })
      return `${labelNum * 14 + 30}px`
    },
    defaultParams() {
      return {
        label: 'label',
        value: 'value',
        children: 'children'
      }
    }
  },
  created() {
    this.fields.forEach((field, i) => {
      Vue.set(this.queryFields, field.prop, field.defaultVal || '')
      this.rules[field.prop] = field.rules
      // eslint-disable-next-line no-prototype-builtins
      if (!field.hasOwnProperty('isShow')) {
        Vue.set(field, 'isShow', true)
      }
      if (field.type === 'tree-select' && field.rules) {
        this.$watch(`queryFields.${field.prop}`, () => {
          this.$refs.ruleForm && this.$refs.ruleForm.validateField(field.prop)
        })
      }
    })
    this.extraFields.forEach((field, i) => {
      Vue.set(this.queryFields, field.prop, field.defaultVal || '')
    })
    this.setBtns()
  },
  mounted() {
    this.autoQuery && this.search()
  },
  methods: {
    setBtns() {
      if (this.needAuth) {
        const btn = getTableBtns(this.handlebtns)
        this.addBtn = btn.add
        this.operaBtns = btn.others
      } else {
        this.handlebtns.forEach((btn) => {
          operaBtns.forEach((btn2) => {
            if (btn === btn2.btn_type) {
              this.operaBtns.push(btn2)
            }
          })
        })
      }
    },
    queryPage(pageNo) {
      if (pageNo) {
        this.pageNo = pageNo
      }
      let flag = false
      if (this.beforeQueryPage) {
        flag = this.beforeQueryPage()
      }
      if (flag) return
      if (this.tableData.length === 1 && this.pageNo > 1) {
        this.pageNo--
      }

      if (this.$refs.ruleForm) {
        this.$refs.ruleForm.validate((valid) => {
          if (!valid) return this.$message.error('校验失败！请检查输入项！')
          this.query()
        })
      } else {
        this.query()
      }
    },
    query() {
      this.loading = true
      const params = {
        pageNo: this.pageNo,
        pageSize: this.pageSize
      }

      const formatDateProp = []
      this.fields.forEach((item) => {
        if (item.formatCurrentMonthDay) {
          formatDateProp.push(item.prop)
        }
      })
      forEach(this.queryFields, (item, prop) => {
        if (formatDateProp.indexOf(prop) > -1) {
          params[prop] = getCurrentMonthDay(item)
        } else {
          params[prop] = item || ''
        }
      })

      const param = {
        baseURL: process.env.VUE_APP_BASE_MOCK_API,
        url: this.queryurl,
        method: 'post',
        data: params
      }
      if (this.ifMock) {
        param.baseURL = process.env.VUE_APP_BASE_MOCK_API
      }
      request(param)
        .then((data) => {
          this.loading = false

          // 翻页和下拉根据后端返回自动识别
          if (Array.isArray(data)) {
            this.totalSize = 0
            this.tableData = data
          } else {
            this.pageNo = data.currenPage
            this.pageSize = data.pageSize
            this.totalSize = data.total
            this.tableData = data.list
          }
        })
        .catch((er) => {
          this.loading = false
        })
    },
    search() {
      this.pageNo = 1
      this.queryPage()
    },
    resetAll() {
      this.$refs.ruleForm.resetFields()
      this.$refs.treeS && this.$refs.treeS[0].setOrg()
      this.pageNo = 1
      this.totalSize = 0
      this.tableData = []
    },
    sizeChange(pageSize) {
      this.pageSize = pageSize
      this.queryPage(1)
    },
    pageChange(pageNo) {
      this.pageNo = pageNo
      this.queryPage()
    },
    tableDataChanged(data) {
      this.$emit('tableDataChanged', data)
    },
    handleData(type, data) {
      this.$emit('handleData', type, data)
    },
    addData() {
      this.handleData('add')
    },
    handleSelectionChange(val) {
      this.$emit('handleSelectionChange', val)
    },
    rowSingleChange(data, index) {
      this.$emit('rowSingleChange', data, index)
    }
  }
}
</script>

<style lang="scss" scoped>
.opera-btns {
  margin-bottom: 25px;
}
</style>
